home *** CD-ROM | disk | FTP | other *** search
Korn shell script | 1997-08-26 | 7.5 KB | 265 lines |
- #!/bin/ksh
- # @(#) chkbackup.ksh 2.1 96/06/21
- # 95/05/28 john h. dubois iii (john@armory.com)
- # 95/06/26 Added all options.
- # 96/04/08 Try /dev/nrStp0 in addition to /dev/nrct0. Added t option.
- # 96/06/16 Added uN options.
- # 96/06/21 Write status to logfile. Added L option. Print tape amount info.
-
- # Usage: mkfiles name ...
- # Creates the named files with some attempt at security.
- # This will be more reliable if user do not have chown authority.
- # Any file that contains no / characters is created in the user's tempdir.
- # If TMP was not set, it is set by this function (but not exported).
- # Returns 0 on success; prints a diagnostic message & returns 1 on failure.
- function mkfiles {
- typeset file files
- typeset -i i=0
-
- : ${TMP:=$TMPDIR}
- : ${TMP:=/tmp}
- for file; do
- [[ "$file" != */* ]] && file="$TMP/$file"
- files[i]=$file
- let i+=1
- done
- set -- "${files[@]}"
-
- rm -f "$@" || {
- # hopefully rm will have printed a more specific message.
- print -r -u2 "Could not remove pre-existing files."
- return 1
- }
- for file; do
- # Use >> to avoid 0'ing the file in case a symlink was just made from
- # the filename to something we don't want to truncate
- >> "$file" || {
- print -r -u2 "Could not create temp file $file"
- return 1
- }
- # These are very suspicious
- [ -s "$file" ] && {
- print -r -u2 "New tempfile is not empty!!!"
- return 1
- }
- [ -O "$file" ] || {
- print -r -u2 "Do not own $file!!!"
- return 1
- }
- done
- # Could do some more stuff here, but anyone concerned with security should
- # have chown authorization off for most users.
- return 0
- }
-
- # Usage: mktempfile name
- # Creates a tempfile name tempdir/#name$$, and sets the global mktempfile_ret
- # to that name. tempdir is a temp directory in $TMP, $TMPDIR, or /tmp, and $$
- # is the PID of the current process.
- # name should be 8 characters or less, so that the resulting filename will
- # not be more than 14 characters long (a limit on some machines).
- # Returns 0 on success, prints a diagnostic message & returns 1 on failure.
- function mktempfile {
- typeset file="#$1$$"
- mkfiles "$file"
- mktempfile_ret="$TMP/#$1$$"
- }
-
- function lprint {
- print -r -- "$*"
- $log && print -r -- "$*" >> "$logfile"
- }
-
- function Rewind {
- if $rewind; then
- print -r "*** Rewinding..."
- tape rewind $nr_device || {
- print -ru2 -- "$longname: Rewind of $nr_device failed. Exiting."
- exit 1
- }
- fi
- }
-
- function check {
- typeset -i status
-
- let extent+=1
- lprint "*** `date` Checking extent $extent"
- $debug && set -x
- if [ -n "$Uncompress" ]; then
- nice -n $nice $Uncompress | nice -$nice "${cmd[@]}"
- else
- nice -n $nice "${cmd[@]}"
- fi < $nr_device >&3
- status=$?
- $debug && set +x
- return $status
- }
-
- nr_device1=/dev/nrct0
- nr_device2=/dev/nrStp0
- nr_device=
- longname=${0##*/}
- rewind=true
- debug=false
- log=true
- defaultCommand="cpio -it -C 65536"
- def_nice=15
- typeset -i nice=$def_nice
- typeset -i maxExtent=0
- Usage=\
- "Usage: $longname [-hLnv] [-e<extents>] [-d<device>] [-u<uncompress-command>]
- [archive listing command]"
- exec 3>/dev/null # default dest for file lists
-
- while getopts :hLnN:e:d:vxu: opt; do
- case $opt in
- h)
- print -r -- \
- "$longname: Check tape backups.
- $Usage
- $longname reads all of the file extents (tape sections between filemarks) on a
- tape and passes them through a command to test the archive integrity of each
- backup. The default command is \"$defaultCommand\". An alternate command can
- be given at the end of the command line that $longname is invoked with. It
- will be run for each file extent in turn, with the tape device passed as its
- input and it standard output (which would typically be a listing of the
- archive) discarded so that only errors will be displayed. The archive listing
- command should not actually extract files onto disk. The command will be
- repeatedly invoked, either as many times as specified with the -e option (if
- given) or until it exits nonzero, whichever comes first. If -e is not given,
- the report produced by $longname should give a good status for the number of
- archives stored on the tape, and then one failure when it tries to read beyond
- the end of the last position on the tape that has been written to.
- For each extent successfully read, a status line and a report of the amount of
- data read from tape is printed. The same information is written to a logfile
- named /tmp/#chkback.pid, where pid is the process ID of the program. To get
- the tape amount information, the tape control device is used. The name of the
- control device is determined by replacing everything up through a leading 'r'
- in the trailing component of the device name with 'x'. For example, the
- control device for /dev/nrStp0 would be /dev/xStp0.
- Options:
- -h: Print this help.
- -n: Do not rewind the tape device before or after checking the backups.
- -e<extents>: Check only the number of extents specified.
- -d<device>: Use <device> instead of the default of $nr_device1 or (if it does
- not exist) $nr_device2. <device> should be a no-rewind device.
- -L: Do not create or write to the logfile.
- -N<nice-increment>: Use <nice-increment> when running uncompressing and archive
- listing commands. The default is $def_nice.
- -u<uncompress-command>: Pass the archive data through <uncompress-command>
- before giving it to the archiving listing command. This could also be done
- by making the uncompress-command part of the archive listing command.
- However, if the default archive listing command is correct, using -u avoids
- the need to give the archive listing command explicitly.
- -v: Verbose. Print files found."
- exit 0
- ;;
- N)
- nice=$OPTARG || exit 1
- ;;
- n)
- rewind=false
- ;;
- d)
- nr_device=$OPTARG
- [[ "$nr_device" != */* ]] && nr_device=/dev/$nr_device
- ;;
- e)
- maxExtent=$OPTARG || {
- print -ru2 -- "$longname: Bad number given with -e. Exiting."
- exit 1
- }
- ;;
- u)
- Uncompress=$OPTARG
- ;;
- L)
- log=false;;
- v)
- exec 3>&1
- ;;
- x)
- debug=true
- ;;
- +?)
- print -ru2 -- "$longname: options should not be preceded by a '+'."
- exit 1
- ;;
- :)
- print -r -u2 -- \
- "$longname: Option '$OPTARG' requires a value. Use -h for help."
- exit 1
- ;;
- ?)
- print -ru2 -- "$longname: $OPTARG: bad option. Use -h for help."
- exit 1
- ;;
- esac
- done
-
- # remove args that were options
- let OPTIND=OPTIND-1
- shift $OPTIND
-
- if [ $# -lt 1 ]; then
- set -A cmd $defaultCommand
- else
- set -A cmd "$@"
- fi
-
- # Find which device to use
- if [ -z "$nr_device" ]; then
- if [ -c $nr_device1 ]; then
- nr_device=$nr_device1
- elif [ -c $nr_device2 ]; then
- nr_device=$nr_device2
- else
- print -ru2 -- \
- "$longname: Neither $nr_device1 nor $nr_device2 exists. Exiting."
- exit 1
- fi
- elif [ ! -c "$nr_device" ]; then
- print -ru2 -- \
- "$longname: $nr_device does not exist or is not a tape device. Exiting."
- exit 1
- fi
-
- tail=${nr_device##*/}
- xdev="${nr_device%/*}/x${tail#*r}"
- if [ ! -c "$xdev" ]; then
- print -ru2 -- \
- "$longname: Cannot access control device $xdev; skipping tape amounts."
- unset xdev
- fi
-
- if $debug; then
- if [ -n "$xdev" ]; then
- print -ru2 "Using device $nr_device and control device $xdev"
- else
- print -ru2 "Using device $nr_device"
- fi
- fi
-
- typeset -i extent=0
-
- Rewind
-
- if $log; then
- TMP=/tmp # for mkfiles
- mktempfile chkback. || {
- print -ru2 -- "$longname: exiting."
- exit 1
- }
- logfile=$mktempfile_ret
- print -r -- "Writing status information to log file $logfile"
- fi
-
- while [ maxExtent -eq 0 -o extent -lt maxExtent ] && check; do
- [ -n "$xdev" ] && lprint "$(tape amount "$xdev")"
- lprint "*** `date` Extent $extent OK"
- sleep 5
- done
-
- Rewind
-